# -*- coding: utf-8 -*-

"""63. 不同路径 II
一个机器人位于一个 m x n 网格的左上角 （起始点在下图中标记为 “Start” ）。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角（在下图中标记为 “Finish”）。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径？
网格中的障碍物和空位置分别用 1 和 0 来表示。

示例 1：
输入：obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出：2
解释：3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径：
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

示例 2：
输入：obstacleGrid = [[0,1],[0,0]]
输出：1

提示：
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1"""

class Solution:
    """
    定义 f(i,j) 为计算到达位置 (i,j) 的不同路径数
    递归基础：
        f(0, x) = 1
        f(x, 0) = 1
    递归定义：
        f(i,j) = f(i-1, j) + f(i, j-1)
    特定条件：
        f(i,j) = 0      # grid[i][j] = 1, 当某个位置上有障碍物时，该位置不可达。

    将递归运算，按动态规划，转换为递推的状态缓存。
    """
    def uniquePathsWithObstacles(self, obstacleGrid: list) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])

        obstacleGrid[0][0] = 0 if obstacleGrid[0][0] == 1 else 1
        j = 1
        while j < n:
            obstacleGrid[0][j] = 0 if obstacleGrid[0][j] == 1 else obstacleGrid[0][j-1]
            j += 1
        i = 1
        while i < m:
            obstacleGrid[i][0] = 0 if obstacleGrid[i][0] == 1 else obstacleGrid[i-1][0]
            i += 1

        i = 1
        while i < m:
            j = 1
            while j < n:
                obstacleGrid[i][j] = 0 if obstacleGrid[i][j] == 1 else (obstacleGrid[i][j-1] + obstacleGrid[i-1][j])
                j += 1
            i += 1

        return obstacleGrid[m-1][n-1]

if __name__ == '__main__':
    print(Solution().uniquePathsWithObstacles([[0,1],[0,0]]))
